"""
Copyright (c) 2007 Daniel Garcia Moreno <danigm@gmail.com>
Copyright (c) 2007 Eduardo Robles Elvira <edulix@gmail.com>
Licence: GPLv2
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
"""
from Vertex import *
import pdb
import Algorithm
import copy

class Graph:
	def __init__(self, vertices, edges=None):
		"""
		if it recieves one argument only, @vertices is the file that contains
		the graph especification.
		
		@vertices is the vertices of the graph, with its adjacent vertices
		@edges is a dictionary with the edges and its weigth. edges[("A","B")] = 15
		"""
		if edges == None:
			self.load_from_file(vertices)
		else:
			self._vertices = vertices
			self._edges = edges
		
	def get_vertices(self):
		""" return a vector of vertex """
		return self._vertices
		
	def set_vertices(self, vertices):
		self._vertices = vertices
		
	def get_edges(self):
		return self._edges
		
	def set_edges(self, edges):
		self._edges = edges
		
	def get_weight(self, src, dst):
		try:
			ret = self._edges[(src,dst)]
		except:
			ret = self._edges[(dst,src)]
			
		return ret
		
	def find_by_name(self, name):
		""" 
		Find a vertex in the graph by its name, if not exist, return None
		"""
		for i in self._vertices:
			if i.get_name() == name:
				return i
		return None

	def find_by_pos(self, x, y):
		"""
		Find a vertex in the graph by its pos
		"""
		for i in self._vertices:
			if x-10 < i.get_x() < x+10 and y-10 < i.get_y() < y+10:
					return i

		return None

	
	#we need to do this if we want that load from file work.
	def load_from_file(self,fichero):
		print "Loading vertices from " + fichero + "..."
		self._edges = {}
		self._vertices = []
		vertices_file = open(fichero)
		edges = None
		
		for line in vertices_file:
			if line[0:6] == "edges:":	#while line == edges begin the edges especification
				edges = True
				continue
				
			if not edges:
				name = line[0:line.index(',')]
				line = line[line.index(',')+1:]
				pos_x = int(line[0:line.index(',')])
				line = line[line.index(',')+1:]
				pos_y = int(line[0:line.index(',')])
				vertex = Vertex(name, [], (pos_x,pos_y))
				self._vertices.append(vertex)
			else:
				u = line[0:line.index(',')]
				line = line[line.index(',')+1:]
				v = line[0:line.index(',')]
				line = line[line.index(',')+1:]
				weight = int(line[0:line.index(',')])
				vertex_u = self.find_by_name(u)
				vertex_v = self.find_by_name(v)
				vertex_u.add_adjacent(vertex_v) #adding new adjacent vertex to u
				vertex_v.add_adjacent(vertex_u) #adding new adjacent vertex to v
				self._edges[(u,v)] = weight #adding new edge
		vertices_file.close()
		print "all vertices loaded OK!"

	def save_to_file(self, fichero):
		f = open(fichero, 'w')
		print "saving to file"
		
		
		for i in self._vertices:
			x, y = i.get_pos()
			name = i.get_name()
			f.write(name + "," + str(x) + "," + str(y) + ",\n")
		dic = {}
		
		g2 = copy.deepcopy(self)
		print "COPIA:"
		g2.print_graph()
		f.write("edges:\n")
		for i in g2._vertices:
			#pdb.set_trace()
			while len(i.get_adjacents()) > 0:
				j = i.get_adjacents()[0]
				weight = str(self.get_weight(i.get_name(), j.get_name()))
				f.write(i.get_name() + "," + j.get_name() + "," + weight + ",\n")
				Algorithm.remove_edge(i, j, g2)
		f.close()

	#this function print a Graph, as a list of vertex with its adjacents
	def print_graph(self):
		print "graph:"
		for v in self.get_vertices():
			to_print = '--'+v.get_name()+': '
			for a in v.get_adjacents():
				to_print += a.get_name()+'->'
			print to_print
		print "end of graph"

